#include "SimpleTables.h"

#include "memdb/impl/Factory.h"
#include "memdb/impl/simple/SimpleTable.h"
#include "memdb/error/MemdbError.h"


namespace memdb {
namespace impl {
namespace simple {


SimpleTables::SimpleTables(IMeta & meta, const Factory & factory)
: _meta(meta)
, _factory(factory)
{
	_meta.iterator()->foreach([this](auto & item){
      auto * tab = new SimpleTable(_meta, _factory.createData(item->first));
			this->mem.emplace(std::make_pair(item->first, tab));
	});
}
SimpleTables::~SimpleTables() {
  for(auto & [_, tab] : mem){
    delete tab;
    tab = nullptr;
  }
}

std::pair<std::error_code, SimpleTables::ValueType> SimpleTables::create(const KeyType & name) {
  auto * tab = new SimpleTable(_meta, _factory.createData(name));

	mem.insert(std::make_pair(name, tab));

	if(auto && ec = _meta.insert(name, name); ec) 
		return std::make_pair(ec, nullptr);
	return std::make_pair(memdb::error::ok, tab);
}

std::error_code SimpleTables::drop(const KeyType & name) {
  auto && iter = mem.find(name);
	if(iter != mem.end()){ // find it
		auto * tab = iter->second;
		delete tab;

		mem.erase(iter);
		if(auto && ec = _meta.remove(name); ec) return ec;
		return memdb::error::ok;
	}
	return memdb::error::table_not_exists;
}

bool SimpleTables::exists(const KeyType & name) const {
	return mem.find(name) != mem.end();
}
std::optional<SimpleTables::ValueType> SimpleTables::get(const KeyType & name) const {
	auto iter = mem.find(name);	
	if(iter != mem.end()){
		return std::make_optional(iter->second);
	}
	return std::nullopt;
}
size_t SimpleTables::count() const {
	return mem.size();
}

SimpleTables::Iterator::Iterator(SimpleTables * tables) 
: _current(tables->mem.begin()) 
, _end(tables->mem.end())
{
}

SimpleTables::Iterator::~Iterator() {
}

std::optional<ITables::Item> SimpleTables::Iterator::next() {
  if(_current != _end){
    auto && o = std::make_optional<ITables::Item>(&*_current);
    ++_current;
    return o;
  }
  return std::nullopt;
}

std::unique_ptr<ITables::Iterator> SimpleTables::iterator() const {
  return std::unique_ptr<ITables::Iterator>(new SimpleTables::Iterator(const_cast<SimpleTables*>(this)));
}

}//namespace simple
}//namespace impl
}//namespace memdb
